﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DSheet.Core.Data
{
    public class DTree
    {
        public int Level { get; set; }
        public List<DTreeNode> Nodes { get; set; }
        public ComboDim Dim { get; set; }

        /// <summary>
        /// 平面化之后的数据行
        /// </summary>
        private List<DRow> _rows;

        public DTree()
        {
            Nodes = new List<DTreeNode>();
        }

        public List<DRow> Complanate()
        {
            if (_rows == null)
            {
                List<DRow> rows = new List<DRow>();

                int dCount = Dim.RelationChain.Relations.Count + 1;
                DTreeNode[] lineNodes = new DTreeNode[dCount];

                Stack<DTreeNode> stack = new Stack<DTreeNode>();
                for (int index = Nodes.Count - 1; index >= 0; index--)
                {
                    stack.Push(Nodes[index]);
                }

                while (stack.Count > 0)
                {
                    DTreeNode node = stack.Pop();
                    lineNodes[node.Tree.Level] = node;

                    if (node.NextTree != null)
                    {
                        for (int index = node.Nodes.Count - 1; index >= 0; index--)
                        {
                            stack.Push(node.Nodes[index]);
                        }

                        for (int index = node.NextTree.Nodes.Count - 1; index >= 0; index--)
                        {
                            stack.Push(node.NextTree.Nodes[index]);
                        }
                    }
                    else
                    {
                        DRow row = new DRow();
                        row.RowIndex = rows.Count;
                        rows.Add(row);

                        row.Items = new DItem[dCount];
                        row.Items[node.Tree.Level] = new DItem();
                        row.Items[node.Tree.Level].Level = node.Level;
                        row.Items[node.Tree.Level].Code = node.Code;
                        row.Items[node.Tree.Level].Name = node.Name;
                        row.Items[node.Tree.Level].Formula = node.Formula;
                        for (int treeIndex = node.Tree.Level - 1; treeIndex >= 0; treeIndex--)
                        {
                            row.Items[treeIndex] = new DItem();
                            row.Items[treeIndex].Level = lineNodes[treeIndex].Level;
                            row.Items[treeIndex].Code = lineNodes[treeIndex].Code;
                            row.Items[treeIndex].Name = lineNodes[treeIndex].Name;
                            row.Items[treeIndex].Formula = lineNodes[treeIndex].Formula;
                        }

                        for (int index = node.Nodes.Count - 1; index >= 0; index--)
                        {
                            stack.Push(node.Nodes[index]);
                        }
                    }
                }

                _rows = rows;
                return rows;
            }
            return _rows;
        }

        private void PushRoot(Stack<DTreeNode> stack, DTreeNode root)
        {
            for (int index = root.Nodes.Count - 1; index >= 0; index--)
            {
                stack.Push(root.Nodes[index]);
                PushRoot(stack, root.Nodes[index]);
            }
        }
    }

    public class DTreeNode
    {
        public DTree Tree { get; set; }
        public DTree NextTree { get; set; }
        public int Level { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public string Formula { get; set; }

        /// <summary>
        /// 下级节点列表
        /// </summary>
        public List<DTreeNode> Nodes { get; set; }

        public DTreeNode()
        {
            Nodes = new List<DTreeNode>();
        }

        public override string ToString()
        {
            return string.Format("{0}-{1}({2})", this.Level, this.Name, this.Code);
        }
    }
}
